﻿using Dapper;
using CommServer.Common;
using CommServer.Common.Database;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;

namespace CommServer.Cache
{
    //分布式情况下需要用redis实现
    public class CacheDevices
    {
        private static object m_SynObject = new object();
        private static Dictionary<string, dynamic> m_Devices = new Dictionary<string, dynamic>();
        private static Dictionary<string, DateTime> m_LastInvTime = new Dictionary<string, DateTime>();
        private static Dictionary<string, DateTime> m_LastMeterTime = new Dictionary<string, DateTime>();
        private static Dictionary<string, DateTime> m_LastAlarmTime = new Dictionary<string, DateTime>();
		private static Dictionary<string, DateTime> m_LastSensorTime = new Dictionary<string, DateTime>();
        private static Dictionary<string, Dictionary<string,dynamic>> m_errors = new Dictionary<string, Dictionary<string, dynamic>>();
        public static void Load()
        {
            string Sql = @"select B.*  from collector A" +
               " inner join deviceinfo B on A.PlantSn = B.PlantSn and A.PlantUnit=B.PlantUnit";
            using (var conn = DbHelper.GetConn())
            {
                var Rows = conn.Query(Sql);

                lock ((m_Devices as IDictionary).SyncRoot)
                {
                    m_Devices.Clear();
                    foreach (var Row in Rows)
                    {
                        dynamic deviceInfo = new ExpandoObject();
                        deviceInfo.SynToServer = false;
                        deviceInfo.Row = Row;
                        m_Devices.Add(Row.PlantUnit + Row.DevAddr, deviceInfo);
                    }
                }
                Sql = "select  * from modtypeerrorcode order by modtype,seqno";
                Rows = conn.Query(Sql);
                lock((m_errors as IDictionary).SyncRoot)
                {
                    m_errors.Clear();
                    foreach(var row in Rows)
                    {
                        if(row.ErrorCode==null)
                        {
                            continue;
                        }
                        Dictionary<string, dynamic> errorcodes = new Dictionary<string, dynamic>();
                        if(m_errors.ContainsKey(row.ModType.ToString()))
                        {
                            errorcodes = m_errors[row.ModType.ToString()];
                        }
                        else
                        {
                            m_errors.Add(row.ModType.ToString(), errorcodes);
                        }
                        if(!errorcodes.ContainsKey(row.ErrorCode.ToString()))
                        {
                            errorcodes.Add(row.ErrorCode.ToString(), row);
                        }
                    }
                }
               /* Sql = "select  * from mqtt_device ";
                Rows = conn.Query(Sql);
                lock((m_MqttConfig as IDictionary).SyncRoot)
                {
                    m_MqttConfig.Clear();
                    foreach (var row in Rows)
                    { 
                        MQTT_KD_Interface mqttServer = new MQTT_KD_Interface(row.MQTTServer,row.Port,row.accessKey,row.secretKey,row.groupId,row.deviceId,false,true);
                        mqttServer.Topic = row.topic;
                        m_MqttConfig.Add(row.PlantUnit, mqttServer);
                    }
                }
                Sql = "select * from AliyunIOTDevices ";
                Rows = conn.Query(Sql);
                lock((m_IOTConfig as IDictionary).SyncRoot)
                {
                    m_IOTConfig.Clear();
                    foreach(var row in Rows)
                    {
                        AliyunIOT.AliyunIOT_Interface IOTServer = new AliyunIOT.AliyunIOT_Interface(row.Region, row.Product, row.Device, row.AccessKey, row.SecretKey, row.Action);
                        m_IOTConfig.Add(row.PlantUnit, IOTServer);
                    }
                }*/
            }
        }
        /*
        public static AliyunIOT.AliyunIOT_Interface getIOTDevice(string SN)
        {
            if (SN == null)
                return null;
            AliyunIOT.AliyunIOT_Interface o = null;
            m_IOTConfig.TryGetValue(SN, out o);
            return o;
        }
        public static MQTT_KD_Interface getMqttDevice(string SN)
        {
            if (SN == null)
                return null;
            MQTT_KD_Interface o = null;
            m_MqttConfig.TryGetValue(SN, out o);
            return o;
        }*/
        public static dynamic getErrorInfo(string RtuSn,int DevAddr,int errorcode)
        {
            dynamic invInfo = getInvDetailInfo(RtuSn, DevAddr);
            if (invInfo == null)
                return null;
            Dictionary<string,dynamic> o = null;
            lock ((m_errors as IDictionary).SyncRoot)
            {
                m_errors.TryGetValue(invInfo.Row.ModType.ToString(), out o);
                if (o == null)
                    return null;
                dynamic E = null;
                o.TryGetValue(errorcode.ToString(), out E);
                return E;
            }
        }
        public static void UpdateSynInvStatus(string RtuSn,int DevAddr, bool Synced)
        {
            string Key = RtuSn + DevAddr;
            dynamic o = null;
            lock ((m_Devices as IDictionary).SyncRoot)
            {
                if(m_Devices.ContainsKey(Key))
                {
                    m_Devices[Key].SynToServer = Synced;
                }
            }
        }
        public static void UpdateCache(string RtuSn, int DevAddr)
        {
            if ((RtuSn == null) || (RtuSn.Length == 0))
            {
                Log.Error("UpdateCache 参数错误！");
                return;
            }
            string Sql = "select B.* from collector A" +
               " inner join deviceinfo B on A.PlantSn = B.PlantSn and A.PlantUnit=B.PlantUnit" +
               " where B.PlantUnit = '" + RtuSn + "' and B.DevAddr=" + DevAddr;
            using (var conn = DbHelper.GetConn())
            {
                var Row = conn.QueryFirstOrDefault(Sql);
                if (Row == null)
                {
                    return;
                }

                lock ((m_Devices as IDictionary).SyncRoot)
                {
                    if(m_Devices.ContainsKey(RtuSn+DevAddr))
                    {
                        dynamic deviceInfo = m_Devices[RtuSn + DevAddr];
                        deviceInfo.Row = Row;
                    }
                    else
                    {
                        dynamic deviceInfo = new ExpandoObject();
                        deviceInfo.SynToServer = false;
                        deviceInfo.Row = Row;
                        m_Devices .Add(RtuSn + DevAddr, deviceInfo);
                    }
                }
            }
        }
        public static void checkInvData(dynamic invData)
        {
            string RtuSN = invData.RtuSN;
            int DevAddr = invData.Addr;
            string Sql = "select * from inverterpinstance where PlantUnit='" + invData.RtuSN + "' DevAddr=" + invData.Addr;
            using (var conn = DbHelper.GetConn())
            {
                var Row = conn.QueryFirstOrDefault(Sql);
                if(Row==null)
                {
                    if(invData.Data.ContainsKey(201))
                    {
                        invData.Data[201] = 0.0;
                    }
                }
                else
                {
                   // float 
                }
            }
        }

        public static dynamic getInvDetailInfo(string RtuSn,int DevAddr)
        {
            string Key = RtuSn + DevAddr;
            dynamic o = null;
            lock ((m_Devices as IDictionary).SyncRoot)
            {
                m_Devices.TryGetValue(Key, out o);
                return o;
            }
        }
        public static string[] GetPlantSnUnit(string RtuSn, int DevAddr)
        {

            string Key = RtuSn + DevAddr;
            dynamic o=null;
            lock ((m_Devices as IDictionary).SyncRoot)
            {
                m_Devices.TryGetValue(Key, out o);
                if(o==null)
                {
                    return null;
                }
                else
                {
                    return new string[] { o.Row.PlantSn, o.Row.PlantUnit, o.Row.DevName };
                }
            }
        }
        public static List<string>Devices
        {
            get { return m_Devices.Keys.ToList(); }
        }
        public static void UpdateLastInvTime(string RtnSn, int Addr, DateTime Time)
        {
            lock ((m_LastInvTime as IDictionary).SyncRoot)
            {
                m_LastInvTime[RtnSn + Addr] = Time;
            }
        }
		 public static DateTime GetLastSensorTime(string RtuSn, int Addr)
        {
            lock ((m_LastSensorTime as IDictionary).SyncRoot)
            {
                var key = RtuSn + Addr;
                if (m_LastSensorTime.ContainsKey(key))
                {
                    return m_LastSensorTime[key];
                }
                return new DateTime();
            }
        }
		internal static void UpdateLastSensorTime(string RtuSn, int Addr, DateTime writeTime)
        {
            lock ((m_LastSensorTime as IDictionary).SyncRoot)
            {
                m_LastSensorTime[RtuSn + Addr] = writeTime;
            }
        }
        public static DateTime GetLastInvTime(string RtnSn, int Addr)
        {
            lock ((m_LastInvTime as IDictionary).SyncRoot)
            {
                var key = RtnSn + Addr;
                if (m_LastInvTime.ContainsKey(key))
                {
                    return m_LastInvTime[key];
                }
                return new DateTime();
            }
        }
        public static DateTime GetLastInvTimeNew(string RtnSn, int Addr)
        {
            lock ((m_LastInvTime as IDictionary).SyncRoot)
            {
                var key = RtnSn + Addr;
                if (m_LastInvTime.ContainsKey(key))
                {
                    return m_LastInvTime[key];
                }
                return new DateTime(2001,01,01);
            }
        }
        public static void UpdateLastMeterTime(string RtnSn, int Addr, DateTime Time)
        {
            lock ((m_LastMeterTime as IDictionary).SyncRoot)
            {
                m_LastMeterTime[RtnSn + Addr] = Time;
            }
        }
        public static DateTime GetLastMeterTime(string RtnSn, int Addr)
        {
            lock ((m_LastMeterTime as IDictionary).SyncRoot)
            {
                var key = RtnSn + Addr;
                if (m_LastMeterTime.ContainsKey(key))
                {
                    return m_LastMeterTime[key];
                }
                return new DateTime();
            }
        }

        public static void UpdateLastAlarmTime(string RtnSn, int Addr, string Note, DateTime Time)
        {
            lock ((m_LastAlarmTime as IDictionary).SyncRoot)
            {
                m_LastAlarmTime[RtnSn + Addr + Note] = Time;
            }
        }
        public static DateTime GetLastAlarmTime(string RtnSn, int Addr, string Note)
        {
            lock ((m_LastAlarmTime as IDictionary).SyncRoot)
            {
                var key = RtnSn + Addr  + Note;
                if (m_LastAlarmTime.ContainsKey(key))
                {
                    return m_LastAlarmTime[key];
                }
                return new DateTime();
            }
        }
    }
}
